//******************************************************************
//******************************************************************
//**********          ANts Peer To Peer Sources        *************
//
// ANts P2P realizes a third generation P2P net. It protects your
// privacy while you are connected and makes you not trackable, hiding
// your identity (ip) and crypting everything you are sending/receiving
// from others.

// Copyright (C) 2004  Roberto Rossi

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package ants.p2p.gui;

import java.awt.*;
import javax.swing.*;
import java.beans.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.event.*;
import javax.swing.table.*;

import ants.p2p.*;
import ants.p2p.query.*;
import ants.p2p.query.security.*;
import ants.p2p.utils.indexer.*;

import org.apache.log4j.*;

import com.borland.jbcl.layout.*;
import javax.swing.border.*;

/**
 * This code was edited or generated using CloudGarden's Jigloo SWT/Swing GUI
 * Builder, which is free for non-commercial use. If Jigloo is being used
 * commercially (ie, by a corporation, company or business for any purpose
 * whatever) then you should purchase a license for each developer using Jigloo.
 * Please visit www.cloudgarden.com for details. Use of Jigloo implies
 * acceptance of these licensing terms. A COMMERCIAL LICENSE HAS NOT BEEN
 * PURCHASED FOR THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED LEGALLY FOR
 * ANY CORPORATE OR COMMERCIAL PURPOSE.
 */
public class QueryAntPanel extends JPanel implements PropertyChangeListener {
	public static String pic = "backgrounds/bg3.jpg";
	static Logger _logger = Logger.getLogger(QueryAntPanel.class.getName());

	Image buffer;
	JScrollPane jScrollPane1 = new JScrollPane();
	public JTextField jTextField1 = new JTextField();
	JLabel jLabel1 = new JLabel();
	JButton jButton1 = new JButton();
	JButton jButton2 = new JButton();
	public QueryResultTable resultsTable;
	QueryMessage[] currentQueries = new QueryMessage[0];
	QueryTimer currentTimer = null;
	GuiAnt container;
	JLabel jLabel2 = new JLabel();
	JButton jButton3 = new JButton();

	ArrayList currentResultSet = new ArrayList();
	ArrayList currentSupernodeSet = new ArrayList();
	boolean searchByStringInProgress = false;
	boolean searchByHashInProgress = false;
	JPanel jPanel1 = new JPanel();
	XYLayout xYLayout2 = new XYLayout();
	XYLayout xYLayout3 = new XYLayout();
	JPanel jPanel2 = new JPanel();
	XYLayout xYLayout4 = new XYLayout();
	FlowLayout flowLayout1 = new FlowLayout(FlowLayout.LEFT);
	Border border1;
	JProgressBar jProgressBar1 = new JProgressBar();
	JButton jButton4 = new JButton();
	JComboBox jComboBox1 = new JComboBox();
	public JCheckBox jCheckBox1 = new JCheckBox();

	public QueryAntPanel(GuiAnt container) {
		this.container = container;
		try {
			Toolkit tk = Toolkit.getDefaultToolkit();
			MediaTracker mt = new MediaTracker(this);
			buffer = tk.getImage(this.getClass().getClassLoader().getResource(
					pic));
			mt.waitForAll();
		} catch (Exception e) {
		}
		try {
			jbInit();
		} catch (Exception ex) {
			_logger.error("", ex);
		}
	}

	void jbInit() throws Exception {
		QueryTableModel model = new QueryTableModel(this.currentResultSet);
		TableSorter sorter = new TableSorter(model);
		resultsTable = new QueryResultTable(sorter, this);
		sorter.setTableHeader(resultsTable.getTableHeader());
		resultsTable
				.getTableHeader()
				.setToolTipText(
						ji.JI
								.i("These are your search results, right click for options"));
		border1 = BorderFactory.createEmptyBorder(20, 20, 20, 20);
		this.setLayout(flowLayout1);
		jLabel1.setText(ji.JI.i("Query String or File Hash"));
		jButton1.setMaximumSize(new Dimension(180, 34));
		jButton1.setMinimumSize(new Dimension(180, 34));
		jButton1.setPreferredSize(new Dimension(180, 34));
		jButton1
				.setToolTipText(ji.JI
						.i("Perform a search using the string in the search field (you may use "
								+ "the google syntax, please read ANts help for further insfos)"));
		// jButton1.setText(ji.JI.i("Search by string"));
		jButton1.setIcon(new LabelIcon(ji.JI.i("Search by string"),
				DoubleBuffer.getInstance().getButton(12), jButton1));
		jButton1.addActionListener(new QueryAntPanel_jButton1_actionAdapter(
				this));
		jButton2.setMaximumSize(new Dimension(150, 34));
		jButton2.setMinimumSize(new Dimension(150, 34));
		jButton2.setPreferredSize(new Dimension(150, 34));
		jButton2.setToolTipText(ji.JI.i("Open a new search tab"));
		jButton2.setMargin(new Insets(2, 14, 2, 14));
		// jButton2.setText(ji.JI.i("New Query"));
		jButton2.setIcon(new LabelIcon(ji.JI.i("New Query"), DoubleBuffer
				.getInstance().getButton(14), jButton2));
		jButton2.addActionListener(new QueryAntPanel_jButton2_actionAdapter(
				this));
		jLabel2.setToolTipText(ji.JI.i("Last search state"));
		jLabel2.setText(ji.JI.i("no last search..."));
		jTextField1.setOpaque(true);
		jTextField1.setToolTipText(ji.JI
				.i("Insert a search string, an ants2k or an ed2k link"));
		jTextField1.setText("");
		jTextField1.addKeyListener(new QueryAntPanel_jTextField1_keyAdapter(
				this));
		jButton3.setMaximumSize(new Dimension(180, 34));
		jButton3.setMinimumSize(new Dimension(180, 34));
		jButton3.setPreferredSize(new Dimension(180, 34));
		jButton3
				.setToolTipText(ji.JI
						.i("Perform a search for the given ants2k:// or ed2k:// link inserted "
								+ "in the search field"));
		// jButton3.setText(ji.JI.i("Search by link"));
		jButton3.setIcon(new LabelIcon(ji.JI.i("Search by link"), DoubleBuffer
				.getInstance().getButton(16), jButton3));
		jButton3.addActionListener(new QueryAntPanel_jButton3_actionAdapter(
				this));
		jPanel1.setLayout(xYLayout3);
		jPanel2.setLayout(xYLayout4);
		jScrollPane1.setMaximumSize(new Dimension(32767, 32767));
		jScrollPane1.setMinimumSize(new Dimension(400, 200));
		jScrollPane1.setPreferredSize(new Dimension(400, 200));
		this
				.addComponentListener(new QueryAntPanel_this_componentAdapter(
						this));
		jPanel2.setMinimumSize(new Dimension(600, 100));
		jPanel2.setOpaque(false);
		jPanel2.setPreferredSize(new Dimension(600, 100));
		jPanel2.setRequestFocusEnabled(true);
		jPanel1.setMinimumSize(new Dimension(470, 60));
		jPanel1.setOpaque(false);
		jPanel1.setPreferredSize(new Dimension(470, 60));
		this.setAlignmentX((float) 0.5);
		this.setBorder(border1);
		jProgressBar1.setOrientation(JProgressBar.HORIZONTAL);
		jProgressBar1.setMinimumSize(new Dimension(100, 18));
		jProgressBar1.setPreferredSize(new Dimension(100, 18));
		jProgressBar1
				.setToolTipText(ji.JI
						.i("Search progress, you may receive further results also when this reach "
								+ "its end, this is only an approximative indication!"));
		jProgressBar1.setMinimum(0);
		jProgressBar1.setMaximum((int) Ant.messageTimeout / 1000);
		jButton4.setMaximumSize(new Dimension(150, 34));
		jButton4.setMinimumSize(new Dimension(150, 34));
		jButton4.setPreferredSize(new Dimension(150, 34));
		jButton4.setToolTipText(ji.JI.i("Close this tab"));
		jButton4.setMargin(new Insets(2, 14, 2, 14));
		// jButton4.setText(ji.JI.i("Close"));
		jButton4.setIcon(new LabelIcon(ji.JI.i("Close"), DoubleBuffer
				.getInstance().getButton(13), jButton4));
		jButton4.addActionListener(new QueryAntPanel_jButton4_actionAdapter(
				this));
		jComboBox1.addItem("");
		jComboBox1.addItem(ji.JI.i("Pictures"));
		jComboBox1.addItem(ji.JI.i("Music"));
		jComboBox1.addItem(ji.JI.i("Video"));
		jComboBox1.addItem(ji.JI.i("ISO images"));
		jComboBox1.setSelectedItem("");
		jComboBox1.setMinimumSize(new Dimension(24, 19));
		jComboBox1.setPreferredSize(new Dimension(100, 19));
		jComboBox1.setToolTipText(ji.JI
				.i("Select the file types to be searched"));
		jCheckBox1.setText(ji.JI.i("Content"));
		jCheckBox1.setToolTipText(ji.JI
				.i("Search also in the content of the indexed files"));
		jCheckBox1.setSelected(false);
		jPanel1.add(jLabel2, new XYConstraints(0, 5, -1, -1));
		jPanel1.add(jProgressBar1, new XYConstraints(350, 27, -1, -1));
		jScrollPane1.getViewport().add(resultsTable, null);
		jPanel2.add(jTextField1, new XYConstraints(0, 65, 220, -1));
		jPanel2.add(jLabel1, new XYConstraints(0, 43, -1, -1));
		jPanel2.add(jButton1, new XYConstraints(350, 0, -1, -1));
		jPanel2.add(jButton4, new XYConstraints(0, 0, -1, -1));
		jPanel2.add(jButton2, new XYConstraints(176, 0, -1, -1));
		jPanel2.add(jComboBox1, new XYConstraints(225, 38, -1, -1));
		jPanel2.add(jCheckBox1, new XYConstraints(225, 65, 100, -1));
		jPanel2.add(jButton3, new XYConstraints(350, 50, -1, -1));
		this.add(jPanel2, null);
		this.add(jScrollPane1, null);
		this.add(jPanel1, null);

		TableColumn column = null;
		for (int i = 0; i < this.resultsTable.getModel().getColumnCount(); i++) {
			column = this.resultsTable.getColumnModel().getColumn(i);
			column.setPreferredWidth(QueryResultTable.columnSizes[i]);
		}
		this.resultsTable.getColumnModel().addColumnModelListener(
				new ColumnResizeListener(this.resultsTable));
	}

	void searchByString(boolean discardCurrentResultset) {
		try {
			this.jButton1.setEnabled(false);
			this.jButton3.setEnabled(false);
			Thread.currentThread().setPriority(10);
			synchronized (this.currentResultSet) {
				if (discardCurrentResultset) {
					this.currentResultSet = new ArrayList();
					this.currentSupernodeSet = new ArrayList(BackgroundEngine
							.getInstance().getSupernodeList().keySet());
					Collections.shuffle(this.currentSupernodeSet);
				}
			}
			String query = this.jTextField1.getText();
			if (this.jComboBox1.getSelectedItem().equals(ji.JI.i("Video")))
				query += " +.avi* +.mpeg*";
			if (this.jComboBox1.getSelectedItem().equals(ji.JI.i("Pictures")))
				query += " +.jpg* +.bmp* +.tif* +.gif*";
			if (this.jComboBox1.getSelectedItem().equals(ji.JI.i("Music")))
				query += " +.rm* +.mp3* +.wav*";
			if (this.jComboBox1.getSelectedItem().equals(ji.JI.i("ISO images")))
				query += " +.iso* +.nrg* +.ccd*";
			if (query == null || query.equals(""))
				return;
			QueryNode qn = this.parseQueryString(this.jTextField1.getText());
			AsymmetricProvider ap = new AsymmetricProvider(false);
			// local
			QueryManager queryManager = new QueryManager(qn,
					this.container.cap.warriorAnt);
			ArrayList resultSet = queryManager.resultSet;
			if (discardCurrentResultset && resultSet.size() > 0) {
				this.currentQueries = new QueryMessage[1];
				this.currentQueries[0] = new QueryMessage(qn, ap
						.getPublicHeader());
				_logger.info("Displaying local results...");
				PropertyChangeEvent pce = new PropertyChangeEvent(this,
						"localQueryCompleted", this.currentQueries[0],
						queryManager.resultSet);
				this.processCurrentQuery(pce);
				_logger.info("Ricevuta parte di query file");
			}
			// remote
			boolean nullQuery = false;
			for (int q = 0; q < 3; q++) {
				if (q == 0) {
					this.currentSupernodeSet.retainAll(new ArrayList(
							BackgroundEngine.getInstance().getSupernodeList()
									.keySet()));
					if (this.currentSupernodeSet.size() > 0) {
						java.util.List supernodesSubset = new ArrayList(
								this.currentSupernodeSet
										.subList(
												0,
												(int) Math
														.min(
																5,
																this.currentSupernodeSet
																		.size())));
						this.currentSupernodeSet.removeAll(supernodesSubset);
						if (this.currentSupernodeSet.size() > 0) {
							this.searchByStringInProgress = true;
							jButton1.setIcon(new LabelIcon(ji.JI
									.i("More by string..."), DoubleBuffer
									.getInstance().getButton(12), jButton1));
						} else {
							this.searchByStringInProgress = false;
							jButton1.setIcon(new LabelIcon(ji.JI
									.i("Search by string"), DoubleBuffer
									.getInstance().getButton(12), jButton1));
						}
						MessageWrapper[] queryWrappers = this.container.cap.warriorAnt
								.doSupernodeQuery(qn, ap.getPublicHeader(),
										supernodesSubset);
						int startingIndex = 0;
						if (!discardCurrentResultset) {
							startingIndex = this.currentQueries.length;
							QueryMessage[] tempArray = new QueryMessage[this.currentQueries.length
									+ queryWrappers.length];
							System.arraycopy(this.currentQueries, 0, tempArray,
									0, this.currentQueries.length);
							this.currentQueries = tempArray;
						} else {
							this.currentQueries = new QueryMessage[queryWrappers.length + 2];
						}
						for (int x = 0; x < queryWrappers.length; x++) {
							if (queryWrappers[x].getMessage() != null
									&& queryWrappers[x].getMessage() instanceof QueryMessage) {
								this.currentQueries[x + startingIndex] = (QueryMessage) queryWrappers[x]
										.getMessage();
							} else
								nullQuery = true;
						}
					} else {
						if (discardCurrentResultset) {
							this.currentQueries = new QueryMessage[2];
						}
					}
				} else if (discardCurrentResultset) {
					MessageWrapper queryWrapper = this.container.cap.warriorAnt
							.doQuery(qn, ap.getPublicHeader());
					if (queryWrapper.getMessage() != null
							&& queryWrapper.getMessage() instanceof QueryMessage) {
						this.currentQueries[this.currentQueries.length - q] = (QueryMessage) queryWrapper
								.getMessage();
					} else
						nullQuery = true;
				}
				Thread.currentThread().sleep(1000);
			}
			if (this.currentSupernodeSet.size() > 0) {
				this.jButton1.setEnabled(true);
			}
			if (this.currentTimer != null && this.currentTimer.isAlive()) {
				this.currentTimer.stop();
			}
			this.currentTimer = new QueryTimer(this);
			this.jLabel2.setText(ji.JI.i("Last search (by string)") + ": "
					+ this.jTextField1.getText());
			Component[] tabs = this.container.jTabbedPane1.getComponents();
			for (int x = 0; x < tabs.length; x++) {
				if (tabs[x] == this) {
					int max = this.jTextField1.getText().length();
					if (max > 10)
						max = 10;
					this.container.jTabbedPane1.setIconAt(x, new LabelIcon(
							ji.JI.i("Search")
									+ " ["
									+ this.currentResultSet.size()
									+ "]: "
									+ this.jTextField1.getText().substring(0,
											max), DoubleBuffer.getInstance()
									.getButton(12), this));
					return;
				}
			}
			if (nullQuery) {
				this.jLabel2
						.setText(ji.JI
								.i("Last search (by string) failed! TRY TO DECREASE YOUR NEIGHBOURS, PROBABLY YOU HAVE TOO MANY CONNECTIONS."));
				throw new Exception("Null query Message in MessageWrapper");
			}
		} catch (Exception ex) {
			_logger.error("Errore nella richiesta di esecuzione query", ex);
			this.jButton1.setEnabled(true);
		}
	}

	public void jButton1_actionPerformed(ActionEvent e) {
		if (this.searchByStringInProgress)
			this.searchByString(false);
		else
			this.searchByString(true);
	}

	public QueryNode parseQueryString(String query) {
		QueryNode queryStructure = new QueryStringItem(null, query, jCheckBox1
				.isSelected());
		return queryStructure;
	}

	private void processCurrentQuery(PropertyChangeEvent e) {
		if (e.getPropertyName().equals("queryCompleted")
				|| e.getPropertyName().equals("localQueryCompleted")) {
			synchronized (currentQueries) {
				for (int q = 0; q < this.currentQueries.length; q++) {
					if (this.currentQueries[q] != null) {
						QueryMessage eventQuerySource = (QueryMessage) e
								.getOldValue();
						if (eventQuerySource.getLocalQueryId() == currentQueries[q]
								.getLocalQueryId()) {
							synchronized (this.currentResultSet) {
								this.currentResultSet = this
										.mergeQueryResults((ArrayList) e
												.getNewValue());
								((QueryTableModel) (((TableSorter) this.resultsTable
										.getModel()).getTableModel()))
										.setResultSet(this.currentResultSet);
								this.resultsTable.revalidate();
							}

							Component[] tabs = this.container.jTabbedPane1
									.getComponents();
							for (int x = 0; x < tabs.length; x++) {
								if (tabs[x] == this) {
									int max = this.jTextField1.getText()
											.length();
									if (max > 10)
										max = 10;
									this.container.jTabbedPane1.setIconAt(x,
											new LabelIcon(ji.JI.i("Search")
													+ " ["
													+ this.currentResultSet
															.size()
													+ "]: "
													+ this.jTextField1
															.getText()
															.substring(0, max),
													DoubleBuffer.getInstance()
															.getButton(12),
													this));
									return;
								}
							}
						}
					}
				}
			}
		}
	}

	public void propertyChange(PropertyChangeEvent e) {
		final PropertyChangeEvent event = e;
		Thread processor = new Thread() {
			public void run() {
				processCurrentQuery(event);
			}
		};
		processor.setPriority(1);
		processor.start();
	}

	public ArrayList mergeQueryResults(ArrayList resultSet) {
		ArrayList tupleGroups = this.currentResultSet;
		for (int x = 0; x < resultSet.size(); x++) {
			if (resultSet.get(x) instanceof QueryCompletedFileTuple) {
				if (tupleGroups.contains((QueryCompletedFileTuple) resultSet
						.get(x))) {
					FileTupleGroup ftg = (FileTupleGroup) tupleGroups
							.get(tupleGroups
									.indexOf((QueryCompletedFileTuple) resultSet
											.get(x)));
					if (ftg.tuples.contains(resultSet.get(x))
							&& ftg.tuples.get(ftg.tuples.indexOf(resultSet
									.get(x))) instanceof QueryRemoteFileTuple)
						ftg.tuples.set(ftg.tuples.indexOf(resultSet.get(x)),
								resultSet.get(x));
					else if (!ftg.tuples.contains(resultSet.get(x)))
						ftg.tuples.add(resultSet.get(x));
				} else {
					QueryCompletedFileTuple qft = (QueryCompletedFileTuple) resultSet
							.get(x);
					FileTupleGroup ftg = new FileTupleGroup(qft.getFileHash(),
							qft.getSize());
					ftg.tuples.add(qft);
					tupleGroups.add(ftg);
				}
			} else if (resultSet.get(x) instanceof QueryPartialFileTuple) {
				if (tupleGroups.contains((QueryPartialFileTuple) resultSet
						.get(x))) {
					FileTupleGroup ftg = (FileTupleGroup) tupleGroups
							.get(tupleGroups
									.indexOf((QueryPartialFileTuple) resultSet
											.get(x)));
					if (ftg.tuples.contains(resultSet.get(x))
							&& ftg.tuples.get(ftg.tuples.indexOf(resultSet
									.get(x))) instanceof QueryRemoteFileTuple)
						ftg.tuples.set(ftg.tuples.indexOf(resultSet.get(x)),
								resultSet.get(x));
					else if (!ftg.tuples.contains(resultSet.get(x)))
						ftg.tuples.add(resultSet.get(x));
				} else {
					QueryPartialFileTuple qpft = (QueryPartialFileTuple) resultSet
							.get(x);
					FileTupleGroup ftg = new FileTupleGroup(qpft.getFileHash(),
							qpft.getSize());
					ftg.tuples.add(qpft);
					tupleGroups.add(ftg);
				}
			} else if (resultSet.get(x) instanceof QueryRemoteFileTuple) {
				if (!tupleGroups.contains((QueryRemoteFileTuple) resultSet
						.get(x))
						&& !this.container.cap.warriorAnt.getIdent().equals(
								((QueryRemoteFileTuple) resultSet.get(x))
										.getOwnerID())) {
					QueryRemoteFileTuple qrft = (QueryRemoteFileTuple) resultSet
							.get(x);
					FileTupleGroup ftg = new FileTupleGroup(qrft.getFileHash(),
							qrft.getSize());
					ftg.tuples.add(qrft);
					tupleGroups.add(ftg);
				} else if (!this.container.cap.warriorAnt.getIdent().equals(
						((QueryRemoteFileTuple) resultSet.get(x)).getOwnerID())) {
					QueryRemoteFileTuple qrft = (QueryRemoteFileTuple) resultSet
							.get(x);
					FileTupleGroup ftg = (FileTupleGroup) tupleGroups
							.get(tupleGroups.indexOf(qrft));
					if (ftg.tuples.contains(resultSet.get(x))
							&& ftg.tuples.get(ftg.tuples.indexOf(resultSet
									.get(x))) instanceof QueryRemoteFileTuple) {
						QueryRemoteFileTuple oldQrft = (QueryRemoteFileTuple) ftg.tuples
								.get(ftg.tuples.indexOf(resultSet.get(x)));
						if (oldQrft.getLastTimeSeen().longValue() < qrft
								.getLastTimeSeen().longValue()) {
							ftg.tuples.set(
									ftg.tuples.indexOf(resultSet.get(x)), qrft);
						}
					} else if (!ftg.tuples.contains(resultSet.get(x))) {
						ftg.tuples.add(qrft);
					}
				}
			}
		}
		return tupleGroups;
	}

	void jButton2_actionPerformed(ActionEvent e) {
		QueryAntPanel qap = new QueryAntPanel(this.container);
		this.container.queryPanels.add(qap);
		this.container.jTabbedPane1.add(qap, new LabelIcon(ji.JI.i("Search"),
				DoubleBuffer.getInstance().getButton(12), qap));
		this.container.cap.warriorAnt.getPropertyChangeSupport()
				.addPropertyChangeListener(qap);
	}

	public void resetQueryTimer() {
		if (this.currentTimer != null && this.currentTimer.isAlive()) {
			this.currentTimer.stop();
		}
		this.currentTimer = new QueryTimer(this);
	}

	void searchByHash(boolean discardCurrentResultset) {
		try {
			this.jButton3.setEnabled(false);
			this.jButton1.setEnabled(false);
			Thread.currentThread().setPriority(10);
			synchronized (this.currentResultSet) {
				if (discardCurrentResultset) {
					this.currentResultSet = new ArrayList();
					this.currentSupernodeSet = new ArrayList(BackgroundEngine
							.getInstance().getSupernodeList().keySet());
					Collections.shuffle(this.currentSupernodeSet);
				}
			}
			String query = null;
			boolean antsHash;
			if (this.jTextField1.getText().toLowerCase().split("\\x7c")[0]
					.equals("ed2k://")) {
				try {
					antsHash = false;
					query = this.jTextField1.getText().toLowerCase().split(
							"\\x7c")[4];
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this, ji.JI
							.i("Not a valid ED2K link"), ji.JI
							.i("Error in performing search"),
							JOptionPane.ERROR_MESSAGE);
					return;
				}
			} else if (this.jTextField1.getText().toLowerCase().split("\\x7c")[0]
					.equals("ants2k://")) {
				try {
					antsHash = true;
					query = this.jTextField1.getText().toLowerCase().split(
							"\\x7c")[4];
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this, ji.JI
							.i("Not a valid ANTS2K link"), ji.JI
							.i("Error in performing search"),
							JOptionPane.ERROR_MESSAGE);
					return;
				}
			} else {
				JOptionPane.showMessageDialog(this, ji.JI
						.i("Not a valid ANTS2K or ED2K link"), ji.JI
						.i("Error in performing search"),
						JOptionPane.ERROR_MESSAGE);
				return;
			}
			if (query == null || query.equals(""))
				return;
			QueryNode qsi = new QueryHashItem(null, query,
					antsHash ? QueryHashItem.ANTS_HASH
							: QueryHashItem.ED2K_HASH, false);
			AsymmetricProvider ap = new AsymmetricProvider(false);
			// local
			QueryManager queryManager = new QueryManager(qsi,
					this.container.cap.warriorAnt);
			ArrayList resultSet = queryManager.resultSet;
			if (discardCurrentResultset && resultSet.size() > 0) {
				this.currentQueries = new QueryMessage[1];
				this.currentQueries[0] = new QueryMessage(qsi, ap
						.getPublicHeader());
				_logger.info("Displaying local results...");
				PropertyChangeEvent pce = new PropertyChangeEvent(this,
						"localQueryCompleted", this.currentQueries[0],
						queryManager.resultSet);
				this.processCurrentQuery(pce);
				_logger.info("Ricevuta parte di query file");
			}
			// remote
			boolean nullQuery = false;
			boolean doneSupernodeQuery = false;
			for (int q = 0; q < 3 && !nullQuery && !doneSupernodeQuery; q++) {
				if (q == 0) {
					this.currentSupernodeSet.retainAll(new ArrayList(
							BackgroundEngine.getInstance().getSupernodeList()
									.keySet()));
					if (this.currentSupernodeSet.size() > 0) {
						java.util.List supernodesSubset = new ArrayList(
								this.currentSupernodeSet
										.subList(
												0,
												(int) Math
														.min(
																5,
																this.currentSupernodeSet
																		.size())));
						this.currentSupernodeSet.removeAll(supernodesSubset);
						if (this.currentSupernodeSet.size() > 0) {
							this.searchByHashInProgress = true;
							jButton3.setIcon(new LabelIcon(ji.JI
									.i("More by hash..."), DoubleBuffer
									.getInstance().getButton(12), jButton1));
						} else {
							this.searchByHashInProgress = false;
							jButton3.setIcon(new LabelIcon(ji.JI
									.i("Search by hash"), DoubleBuffer
									.getInstance().getButton(12), jButton1));
						}
						MessageWrapper[] queryWrappers = this.container.cap.warriorAnt
								.doSupernodeQuery(qsi, ap.getPublicHeader(),
										supernodesSubset);
						int startingIndex = 0;
						if (!discardCurrentResultset) {
							startingIndex = this.currentQueries.length;
							QueryMessage[] tempArray = new QueryMessage[this.currentQueries.length
									+ queryWrappers.length];
							System.arraycopy(this.currentQueries, 0, tempArray,
									0, this.currentQueries.length);
							this.currentQueries = tempArray;
						} else {
							this.currentQueries = new QueryMessage[queryWrappers.length + 2];
						}
						for (int x = 0; x < queryWrappers.length && !nullQuery; x++) {
							if (queryWrappers[x].getMessage() != null
									&& queryWrappers[x].getMessage() instanceof QueryMessage) {
								this.currentQueries[x + startingIndex] = (QueryMessage) queryWrappers[x]
										.getMessage();
							} else
								nullQuery = true;
						}
					} else {
						if (discardCurrentResultset) {
							this.currentQueries = new QueryMessage[2];
						}
					}
				} else if (discardCurrentResultset) {
					MessageWrapper queryWrapper = this.container.cap.warriorAnt
							.doQuery(qsi, ap.getPublicHeader());
					if (queryWrapper.getMessage() != null
							&& queryWrapper.getMessage() instanceof QueryMessage) {
						this.currentQueries[this.currentQueries.length - q] = (QueryMessage) queryWrapper
								.getMessage();
					} else
						nullQuery = true;
				}
				Thread.currentThread().sleep(1000);
			}
			if (!nullQuery) {
				if (this.currentSupernodeSet.size() > 0) {
					this.jButton3.setEnabled(true);
				}
				if (this.currentTimer != null && this.currentTimer.isAlive()) {
					this.currentTimer.stop();
				}
				this.currentTimer = new QueryTimer(this);
				this.jLabel2.setText(ji.JI.i("Last search (by hash)") + ": "
						+ this.jTextField1.getText());
				Component[] tabs = this.container.jTabbedPane1.getComponents();
				for (int x = 0; x < tabs.length; x++) {
					if (tabs[x] == this) {
						int max = this.jTextField1.getText().length();
						if (max > 10)
							max = 10;
						this.container.jTabbedPane1.setIconAt(x, new LabelIcon(
								ji.JI.i("Search")
										+ " ["
										+ this.currentResultSet.size()
										+ "]: "
										+ this.jTextField1.getText().substring(
												0, max), DoubleBuffer
										.getInstance().getButton(12), this));
						return;
					}
				}
			} else {
				this.jLabel2
						.setText(ji.JI
								.i("Last search (by hash) failed! TRY TO DECREASE YOUR NEIGHBOURS, PROBABLY YOU HAVE TOO MANY CONNECTIONS."));
				throw new Exception("Null query Message in MessageWrapper");
			}
		} catch (Exception ex) {
			_logger.error("Errore nella richiesta di esecuzione query", ex);
			this.jButton3.setEnabled(true);
		}
	}

	public void jButton3_actionPerformed(ActionEvent e) {
		if (this.searchByHashInProgress)
			this.searchByHash(false);
		else
			this.searchByHash(true);
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (buffer != null) {
			int posX = (this.getWidth() - 650) / 2;
			int posY = (this.getHeight() - 550) / 2;
			if (posX < 0)
				posX = 0;
			if (posY < 0)
				posY = 0;
			// remove by vincent.zhu for not show image
			// g.drawImage(buffer, posX, posY, this);
		}
	}

	void this_componentResized(ComponentEvent e) {
		this.jPanel1.setPreferredSize(new Dimension(this.getWidth(),
				this.jPanel1.getHeight()));
		this.jPanel1.setSize(new Dimension(this.getWidth(), this.jPanel1
				.getHeight()));
		this.jPanel2.setPreferredSize(new Dimension(this.getWidth(),
				this.jPanel2.getHeight()));
		this.jPanel2.setSize(new Dimension(this.getWidth(), this.jPanel2
				.getHeight()));
		this.jScrollPane1.setPreferredSize(new Dimension(this.getWidth() - 50,
				this.getHeight() - 200));
		this.jScrollPane1.setSize(new Dimension(this.getWidth() - 50, this
				.getHeight() - 200));
	}

	void jTextField1_keyReleased(KeyEvent e) {
		if (e.getKeyChar() == '\n') {
			if (this.searchByStringInProgress && this.jButton1.isEnabled())
				this.searchByString(false);
			else if (this.jButton1.isEnabled())
				this.searchByString(true);
		} else {
			this.searchByHashInProgress = false;
			jButton3.setIcon(new LabelIcon(ji.JI.i("Search by hash"),
					DoubleBuffer.getInstance().getButton(12), jButton1));
			this.jButton1.setEnabled(true);
			this.searchByStringInProgress = false;
			jButton1.setIcon(new LabelIcon(ji.JI.i("Search by string"),
					DoubleBuffer.getInstance().getButton(12), jButton1));
			this.jButton3.setEnabled(true);
		}
	}

	void jButton4_actionPerformed(ActionEvent e) {
		this.container.getTabbedPane().remove(this);
	}
}

class QueryAntPanel_jButton1_actionAdapter implements
		java.awt.event.ActionListener {
	QueryAntPanel adaptee;

	QueryAntPanel_jButton1_actionAdapter(QueryAntPanel adaptee) {
		this.adaptee = adaptee;
	}

	public void actionPerformed(ActionEvent e) {
		final ActionEvent event = e;
		Thread processor = new Thread() {
			public void run() {
				adaptee.jButton1_actionPerformed(event);
			}
		};
		processor.setPriority(10);
		processor.start();
	}
}

class QueryAntPanel_jButton2_actionAdapter implements
		java.awt.event.ActionListener {
	QueryAntPanel adaptee;

	QueryAntPanel_jButton2_actionAdapter(QueryAntPanel adaptee) {
		this.adaptee = adaptee;
	}

	public void actionPerformed(ActionEvent e) {
		adaptee.jButton2_actionPerformed(e);
	}
}

class QueryAntPanel_jButton3_actionAdapter implements
		java.awt.event.ActionListener {
	QueryAntPanel adaptee;

	QueryAntPanel_jButton3_actionAdapter(QueryAntPanel adaptee) {
		this.adaptee = adaptee;
	}

	public void actionPerformed(ActionEvent e) {
		final ActionEvent event = e;
		Thread processor = new Thread() {
			public void run() {
				adaptee.jButton3_actionPerformed(event);
			}
		};
		processor.setPriority(10);
		processor.start();
	}
}

class QueryAntPanel_this_componentAdapter extends
		java.awt.event.ComponentAdapter {
	QueryAntPanel adaptee;

	QueryAntPanel_this_componentAdapter(QueryAntPanel adaptee) {
		this.adaptee = adaptee;
	}

	public void componentResized(ComponentEvent e) {
		adaptee.this_componentResized(e);
	}
}

class QueryAntPanel_jTextField1_keyAdapter extends java.awt.event.KeyAdapter {
	QueryAntPanel adaptee;

	QueryAntPanel_jTextField1_keyAdapter(QueryAntPanel adaptee) {
		this.adaptee = adaptee;
	}

	public void keyReleased(KeyEvent e) {
		final KeyEvent event = e;
		final SwingWorker worker = new SwingWorker() {
			public Object construct() {
				adaptee.jTextField1_keyReleased(event);
				return null;
			}
		};
		worker.start();
	}
}

class QueryTimer extends Thread {
	long loops = Ant.messageTimeout / 1000;
	QueryAntPanel caller;

	public QueryTimer(QueryAntPanel caller) {
		this.caller = caller;
		this.setPriority(1);
		this.start();
		while (!this.isAlive())
			try {
				Thread.currentThread().sleep(1000); // .yield()
			} catch (InterruptedException ex) {
			}
		this.caller.jProgressBar1.setValue(0);
	}

	public void run() {
		while (loops > 0) {
			try {
				this.sleep(1000);
			} catch (InterruptedException ex) {
			}
			loops--;
			this.caller.jProgressBar1.setValue(this.caller.jProgressBar1
					.getValue() + 1);
		}
		if (caller.currentSupernodeSet.size() == 0) {
			this.caller.searchByHashInProgress = false;
			this.caller.jButton3.setIcon(new LabelIcon(ji.JI
					.i("Search by hash"), DoubleBuffer.getInstance().getButton(
					12), this.caller.jButton1));
			this.caller.jButton1.setEnabled(true);
			this.caller.searchByStringInProgress = false;
			this.caller.jButton1.setIcon(new LabelIcon(ji.JI
					.i("Search by string"), DoubleBuffer.getInstance()
					.getButton(12), this.caller.jButton1));
			this.caller.jButton3.setEnabled(true);
		}
	}
}

class QueryAntPanel_jButton4_actionAdapter implements
		java.awt.event.ActionListener {
	QueryAntPanel adaptee;

	QueryAntPanel_jButton4_actionAdapter(QueryAntPanel adaptee) {
		this.adaptee = adaptee;
	}

	public void actionPerformed(ActionEvent e) {
		adaptee.jButton4_actionPerformed(e);
	}
}
